home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Games Collection 1 / software vault.zip / software vault / CDR10 / ACK3D.ZIP / TRIG / TRIG.C < prev    next >
C/C++ Source or Header  |  1993-08-20  |  15KB  |  558 lines

  1. /*============================================================================
  2. ACK-3D - Animation Construction Kit 3D
  3.  
  4. Original Author:
  5.     Lary Myers
  6.     5 Jacob Street
  7.     Ballston Lake, NY 12019
  8.     Compuserve: 72355,655
  9.  
  10. Portions by:
  11.     John Gaines, Jr.
  12.     3512 Pear Tree Court #23
  13.     Silver Spring, MD 20906-2577
  14.     Home phone: (301) 871-2635
  15.     Compuserve: 73747,3557
  16.  
  17. File:    trig.c  --  Program to generate TRIG.DAT file.
  18.  
  19. Public Functions:
  20.  
  21.         int  main(int ArgCount, char ** ArgPtrs);
  22.         void ShowHelp(void);
  23.         int  AllocateTables(void);
  24.         int  NullCheckFree(void ** PointerPointer);
  25.         void FreeTables(void);
  26.         void BuildTables(void);
  27.         int  ReadOneTable(FILE * InputFile, long * Table);
  28.         int  ReadTables(char *FileName);
  29.         void PrintOneTable(char * TableName, long * Table);
  30.         void PrintTables(void);
  31.         int  WriteOneTable(FILE * OutputFile, long * Table);
  32.         int  WriteTables(char *FileName);
  33.  
  34. Descr:    
  35.  
  36.   ***revision-history***
  37. 1 TRIG.C 18-Aug-93,22:13:32 Initial version of program to create TRIG.DAT.
  38. 2 TRIG.C 20-Aug-93,2:07:38 Lary's CS #.
  39.   ***revision-history***
  40. ============================================================================*/
  41. #include <stdio.h>
  42. #include <math.h>
  43. #include <alloc.h>
  44. #include <string.h>
  45. #include <limits.h>
  46. #include <float.h>
  47. #include "angle.h"
  48.  
  49. typedef    long double    Real_t;
  50.  
  51. long *    SinTableShift16;
  52. long *    CosTableShift16;
  53. long *    TanTableShift16;
  54. long *    InvTanTableShift16;
  55. long *    InvCosTableShift20;
  56. long *    InvSinTableShift20;
  57. long *    CosTableShift14;
  58. long *    ViewCosTable;
  59.  
  60. #define    TABLE_SIZE    (INT_ANGLE_360 * sizeof(long))
  61.  
  62. const Real_t    Shift14 = 16384.0;
  63. const Real_t    Shift16 = 65536.0;
  64. const Real_t    Shift20 = 1048576.0;
  65. const Real_t    AlmostZero = 0.0000001;
  66.  
  67. Real_t (*RoundFunc)(Real_t);
  68.  
  69. typedef enum {OpCreate, OpRead} Operation_t;
  70. typedef enum {OutputText, OutputBinary} OutputFormat_t;
  71.  
  72. void     ShowHelp(void);
  73. int      AllocateTables(void);
  74. int      NullCheckFree(void ** PointerPointer);
  75. void     FreeTables(void);
  76. void     BuildTables(void);
  77. int      ReadOneTable(FILE * InputFile, long * Table);
  78. int      ReadTables(char *FileName);
  79. void     PrintOneTable(char * TableName, long * Table);
  80. void     PrintTables(void);
  81. int      WriteOneTable(FILE * OutputFile, long * Table);
  82. int      WriteTables(char *FileName);
  83. Real_t    RoundUp(Real_t Value);
  84. Real_t    RoundDown(Real_t Value);
  85. Real_t    RoundIn(Real_t Value);
  86. Real_t    RoundOut(Real_t Value);
  87.  
  88. /*----------------------------------------------------------------------------
  89. Func:    main  --  
  90.  
  91. Descr:    
  92. ----------------------------------------------------------------------------*/
  93. int main(int ArgCount, char ** ArgPtrs)
  94.     {
  95.     char *            OptionCharPtr;
  96.     Operation_t        Operation = OpCreate;
  97.     OutputFormat_t    OutputFormat = OutputText;
  98.     char            FileName[FILENAME_MAX];
  99.  
  100.     fputs( "ACK-3D TRIG.DAT Builder  v1.0  by John Gaines, Jr.\n\n", stderr);
  101.     
  102.     FileName[0] = '\0';
  103.     RoundFunc    = RoundOut;
  104.  
  105.     for (--ArgCount, ++ArgPtrs; ArgCount; --ArgCount, ++ArgPtrs)
  106.         if (**ArgPtrs == '-' || **ArgPtrs == '/')
  107.             {
  108.             OptionCharPtr = (*ArgPtrs) + 1;
  109.             while (*OptionCharPtr)
  110.                 {
  111.                 switch (*OptionCharPtr)
  112.                     {
  113.                     case '?':
  114.                         ShowHelp();
  115.                         return 0;
  116.                     case 'r':
  117.                         Operation = OpRead;
  118.                         ++OptionCharPtr;
  119.                         break;
  120.                     case 'b':
  121.                         OutputFormat = OutputBinary;
  122.                         ++OptionCharPtr;
  123.                         break;
  124.                     case 'u':
  125.                         RoundFunc = RoundUp;
  126.                         ++OptionCharPtr;
  127.                         break;
  128.                     case 'd':
  129.                         RoundFunc = RoundDown;
  130.                         ++OptionCharPtr;
  131.                         break;
  132.                     case 'i':
  133.                         RoundFunc = RoundIn;
  134.                         ++OptionCharPtr;
  135.                         break;
  136.                     case 'o':
  137.                         RoundFunc = RoundOut;
  138.                         ++OptionCharPtr;
  139.                         break;
  140.                     default:
  141.                         printf( "Invalid option character '%c' in \"%s\" argument.\n",
  142.                             *OptionCharPtr, *ArgPtrs);
  143.                         ++OptionCharPtr;
  144.                         break;
  145.                     }
  146.                 }
  147.             }
  148.         else if (FileName[0] == '\0')
  149.             strcpy( FileName, *ArgPtrs);
  150.         else
  151.             {
  152.             printf( "Too many filenames on command line: %s\n", *ArgPtrs);
  153.             ShowHelp();
  154.             return -1;
  155.             }
  156.  
  157.     if (FileName[0] == '\0')
  158.         strcpy( FileName, "TRIG.DAT");
  159.  
  160.     if (AllocateTables())
  161.         {
  162.         printf("Out of memory allocating tables.\n");
  163.         return -1;
  164.         }
  165.  
  166.     if (Operation == OpCreate)
  167.         BuildTables();
  168.     else if (ReadTables( FileName))
  169.         {
  170.         printf( "Error reading tables from %s.\n", FileName);
  171.         return -1;
  172.         }
  173.  
  174.     if (Operation == OpRead || OutputFormat == OutputText)
  175.         PrintTables();
  176.     else
  177.         WriteTables( FileName);
  178.  
  179.     FreeTables();
  180.  
  181.     fputs( "Done.\n", stderr);
  182.  
  183.     return 0;
  184.     }
  185.  
  186. /*----------------------------------------------------------------------------
  187. Func:    ShowHelp  --  
  188.  
  189. Descr:    
  190. ----------------------------------------------------------------------------*/
  191. void ShowHelp(void)
  192.     {
  193.     static char * HelpText[] =
  194.         {
  195.         "Syntax:\t TRIG [options] [filename]",
  196.         "",
  197.         "Options: -?\tShow this help screen.",
  198.         "\t -b\tOutput binary file.",
  199.         "\t -r\tRead binary input from filename.",
  200.         "\t -u\tRound floating point values up when converting to longs.",
  201.         "\t -d\tRound floating point values down when converting to longs.",
  202.         "\t -i\tRound floating point values inward towards zero when converting",
  203.             "\t\tto longs.",
  204.         "\t -o\tRound floating point values outward away from zero when",
  205.             "\t\tconverting to longs.",
  206.         "",
  207.         "If no arguments are given, default operation is to create the trig tables,",
  208.         "rounding floating point values out when converting to longs, and print the",
  209.         "tables out in readable C array format to stdout.",
  210.         (char *)0
  211.         };
  212.     char **    TextPtr;
  213.  
  214.     for (TextPtr = HelpText; *TextPtr; ++TextPtr)
  215.         puts(*TextPtr);
  216.     }
  217.  
  218. /*----------------------------------------------------------------------------
  219. Func:    AllocateTables  --  Allocate memory for all tables.
  220.  
  221. Descr:    
  222. ----------------------------------------------------------------------------*/
  223. int AllocateTables(void)
  224.     {
  225.     fputs( "Allocating memory for tables.\n", stderr);
  226.  
  227.     SinTableShift16       = calloc( INT_ANGLE_360, sizeof(long));
  228.     CosTableShift16       = calloc( INT_ANGLE_360, sizeof(long));
  229.     TanTableShift16       = calloc( INT_ANGLE_360, sizeof(long));
  230.     InvTanTableShift16 = calloc( INT_ANGLE_360, sizeof(long));
  231.     InvCosTableShift20 = calloc( INT_ANGLE_360, sizeof(long));
  232.     InvSinTableShift20 = calloc( INT_ANGLE_360, sizeof(long));
  233.     CosTableShift14       = calloc( INT_ANGLE_360, sizeof(long));
  234.  
  235.     if (SinTableShift16       == NULL ||
  236.         CosTableShift16       == NULL ||
  237.         TanTableShift16       == NULL ||
  238.         InvTanTableShift16 == NULL ||
  239.         InvCosTableShift20 == NULL ||
  240.         InvSinTableShift20 == NULL ||
  241.         CosTableShift14       == NULL)
  242.         return -1;
  243.  
  244.     return 0;
  245.     }
  246.  
  247. /*----------------------------------------------------------------------------
  248. Func:    NullCheckFree  --  Check a pointer NULL before free, then set to NULL.
  249.  
  250. Descr:    
  251. ----------------------------------------------------------------------------*/
  252. int NullCheckFree(void ** PointerPointer)
  253.     {
  254.     if (PointerPointer != NULL)
  255.         {
  256.         if (PointerPointer != NULL)
  257.             free( *PointerPointer);
  258.         *PointerPointer = NULL;
  259.         return 0;
  260.         }
  261.     return -1;
  262.     }
  263.  
  264. /*----------------------------------------------------------------------------
  265. Func:    FreeTables  --  Free all memory allocated by program.
  266.  
  267. Descr:    
  268. ----------------------------------------------------------------------------*/
  269. void FreeTables(void)
  270.     {
  271.     fputs( "Freeing table memory.\n", stderr);
  272.  
  273.     NullCheckFree( &(void *)SinTableShift16      );
  274.     NullCheckFree( &(void *)CosTableShift16      );
  275.     NullCheckFree( &(void *)TanTableShift16      );
  276.     NullCheckFree( &(void *)InvTanTableShift16);
  277.     NullCheckFree( &(void *)InvCosTableShift20);
  278.     NullCheckFree( &(void *)InvSinTableShift20);
  279.     NullCheckFree( &(void *)CosTableShift14      );
  280.     }
  281.  
  282. /*----------------------------------------------------------------------------
  283. Func:    BuildTables  --  Build all trig tables into memory arrays.
  284.  
  285. Descr:    
  286. ----------------------------------------------------------------------------*/
  287. void BuildTables(void)
  288.     {
  289.     Real_t    Radians;
  290.     Real_t    SinValue;
  291.     Real_t    CosValue;
  292.     Real_t    TanValue;
  293.     int        InternalDegree;
  294.  
  295.     fputs( "Building tables...\n", stderr);
  296.  
  297.     /* Stepping by internal degrees and calculating the equivalent radian
  298.         angle at each iteration, we eliminate rounding errors which result
  299.         from incrementing a floating point number at each iteration. */
  300.     
  301.     for (InternalDegree = 0; InternalDegree < INT_ANGLE_360; ++InternalDegree)
  302.         {
  303.         fprintf( stderr, "%d\r", InternalDegree);
  304.  
  305.         /* Radians = (2pi InternalDegree) / INT_ANGLE_360 reduces to: */
  306.  
  307.         Radians = (M_PI * InternalDegree) / (Real_t)INT_ANGLE_180;
  308.  
  309.         SinValue = sinl( Radians);
  310.         CosValue = cosl( Radians);
  311.         if (Radians == M_PI_2 || Radians == (M_PI + M_PI_2))
  312.             TanValue = LONG_MAX / Shift16;
  313.         else
  314.             TanValue = tanl( Radians);
  315.  
  316.         SinTableShift16[InternalDegree]    = (long)(RoundFunc(SinValue * Shift16));
  317.         CosTableShift16[InternalDegree]    = (long)(RoundFunc(CosValue * Shift16));
  318.         TanTableShift16[InternalDegree]    = (long)(RoundFunc(TanValue * Shift16));
  319.         CosTableShift14[InternalDegree]    = (long)(RoundFunc(CosValue * Shift14));
  320.  
  321.         /* When calculating the inverse trig functions, we have to check for
  322.             0.0 values, in which case, we'll put LONG_MAX in our table. */
  323.  
  324.         if (TanValue <= AlmostZero && TanValue >= -AlmostZero)
  325.             InvTanTableShift16[InternalDegree] = LONG_MAX;
  326.         else
  327.             InvTanTableShift16[InternalDegree] = (long)(RoundFunc(1.0 / TanValue * Shift16));
  328.  
  329.         if (CosValue <= AlmostZero && CosValue >= -AlmostZero)
  330.             InvCosTableShift20[InternalDegree] = LONG_MAX;
  331.         else
  332.             InvCosTableShift20[InternalDegree] = (long)(RoundFunc(1.0 / CosValue * Shift20));
  333.  
  334.         if (SinValue <= AlmostZero && SinValue >= -AlmostZero)
  335.             InvSinTableShift20[InternalDegree] = LONG_MAX;
  336.         else
  337.             InvSinTableShift20[InternalDegree] = (long)(RoundFunc(1.0 / SinValue * Shift20));
  338.         }
  339.  
  340.     fputs( "Done building tables.\n", stderr);
  341.     }
  342.  
  343. /*----------------------------------------------------------------------------
  344. Func:    ReadOneTable  --  Read one trig table from binary file.
  345.  
  346. Descr:    
  347. ----------------------------------------------------------------------------*/
  348. int ReadOneTable(FILE * InputFile, long * Table)
  349.     {
  350.     fputc( '.', stderr);
  351.  
  352.     if (fread(Table, sizeof(long), INT_ANGLE_360, InputFile) != INT_ANGLE_360)
  353.         return -1;
  354.  
  355.     return 0;
  356.     }
  357.  
  358. /*----------------------------------------------------------------------------
  359. Func:    ReadTables  --  Read all trig tables from binary file.
  360.  
  361. Descr:    
  362. ----------------------------------------------------------------------------*/
  363. int ReadTables(char *FileName)
  364.     {
  365.     FILE *    InputFile;
  366.     
  367. #define    READ(Table)    if (ReadOneTable(InputFile, Table))    \
  368.                             return -1;
  369.  
  370.     InputFile = fopen( FileName, "rb");
  371.     if (InputFile == NULL)
  372.         {
  373.         return -1;
  374.         }
  375.  
  376.     fputs( "Reading tables", stderr);
  377.  
  378.     READ( SinTableShift16);
  379.     READ( CosTableShift16);
  380.     READ( TanTableShift16);
  381.     READ( InvTanTableShift16);
  382.     READ( InvCosTableShift20);
  383.     READ( InvSinTableShift20);
  384.     READ( CosTableShift14);
  385.  
  386.     fputs( "\nDone reading tables.\n", stderr);
  387.  
  388.     return 0;
  389.     }
  390.  
  391. /*----------------------------------------------------------------------------
  392. Func:    PrintOneTable  --  Print a table in readable C array format to stdout.
  393.  
  394. Descr:    
  395. ----------------------------------------------------------------------------*/
  396. void PrintOneTable(char * TableName, long * Table)
  397.     {
  398.     int        InternalDegree;
  399.     int *    DegreeConvPtr;
  400.  
  401.     static int    DegreeConversionTable[] =
  402.         {
  403.         0,                0,
  404.         INT_ANGLE_1,    1,
  405.         INT_ANGLE_2,    2,
  406.         INT_ANGLE_4,    4,
  407.         INT_ANGLE_6,    6,
  408.         INT_ANGLE_30,    30,
  409.         INT_ANGLE_45,    45,
  410.         INT_ANGLE_90,    90,
  411.         INT_ANGLE_135,    135,
  412.         INT_ANGLE_180,    180,
  413.         INT_ANGLE_225,    225,
  414.         INT_ANGLE_270,    270,
  415.         INT_ANGLE_315,    315,
  416.         INT_ANGLE_360,    360,
  417.         -1
  418.         };
  419.  
  420.     fputc( '.', stderr);
  421.  
  422.     printf( "long %s [] =\n\t{\n", TableName);
  423.  
  424.     DegreeConvPtr = DegreeConversionTable;
  425.  
  426.     for (InternalDegree = 0; InternalDegree < INT_ANGLE_360; ++InternalDegree)
  427.         {
  428.         printf( "\t%ld%s", Table[InternalDegree],
  429.             (InternalDegree == INT_ANGLE_360 - 1) ? "" : ",");
  430.  
  431.         if (InternalDegree == *DegreeConvPtr)
  432.             {
  433.             printf( "\t/* %d */\n", DegreeConvPtr[1]);
  434.             DegreeConvPtr += 2;
  435.             }
  436.         else
  437.             putchar( '\n');
  438.         }
  439.  
  440.     printf( "\t};\n\n");
  441.     }
  442.  
  443. /*----------------------------------------------------------------------------
  444. Func:    PrintTables  --  Print all trig tables to stdout.
  445.  
  446. Descr:    
  447. ----------------------------------------------------------------------------*/
  448. void PrintTables(void)
  449.     {
  450. #define PRINT(tbl)    PrintOneTable( #tbl, tbl)
  451.  
  452.     fputs( "Printing tables", stderr);
  453.  
  454.     PRINT( SinTableShift16);
  455.     PRINT( CosTableShift16);
  456.     PRINT( TanTableShift16);
  457.     PRINT( InvTanTableShift16);
  458.     PRINT( InvCosTableShift20);
  459.     PRINT( InvSinTableShift20);
  460.     PRINT( CosTableShift14);
  461.  
  462.     fputs( "\nDone printing tables.\n", stderr);
  463.     }
  464.  
  465. /*----------------------------------------------------------------------------
  466. Func:    WriteOneTable  --  Write one trig table to binary file.
  467.  
  468. Descr:    
  469. ----------------------------------------------------------------------------*/
  470. int WriteOneTable(FILE * OutputFile, long * Table)
  471.     {
  472.     fputc( '.', stderr);
  473.  
  474.     if (fwrite(Table, sizeof(long), INT_ANGLE_360, OutputFile) != INT_ANGLE_360)
  475.         return -1;
  476.  
  477.     return 0;
  478.     }
  479.  
  480. /*----------------------------------------------------------------------------
  481. Func:    WriteTables  --  Write all trig tables to binary file.
  482.  
  483. Descr:    
  484. ----------------------------------------------------------------------------*/
  485. int WriteTables(char *FileName)
  486.     {
  487.     FILE *    OutputFile;
  488.     
  489. #define    WRITE(Table)    if (WriteOneTable(OutputFile, Table))    \
  490.                             return -1;
  491.  
  492.     OutputFile = fopen( FileName, "wb");
  493.     if (OutputFile == NULL)
  494.         {
  495.         return -1;
  496.         }
  497.  
  498.     fputs( "Writing tables", stderr);
  499.  
  500.     WRITE( SinTableShift16);
  501.     WRITE( CosTableShift16);
  502.     WRITE( TanTableShift16);
  503.     WRITE( InvTanTableShift16);
  504.     WRITE( InvCosTableShift20);
  505.     WRITE( InvSinTableShift20);
  506.     WRITE( CosTableShift14);
  507.  
  508.     fputs( "\nDone writing tables.\n", stderr);
  509.  
  510.     return 0;
  511.     }
  512.  
  513. /*----------------------------------------------------------------------------
  514. Func:    RoundUp  --  Round numbers up towards more positive values.
  515.  
  516. Descr:    
  517. ----------------------------------------------------------------------------*/
  518. Real_t RoundUp(Real_t Value)
  519.     {
  520.     return ceill(Value);
  521.     }
  522.  
  523. /*----------------------------------------------------------------------------
  524. Func:    RoundDown  --  Round numbers down towards more negative values.
  525.  
  526. Descr:    
  527. ----------------------------------------------------------------------------*/
  528. Real_t RoundDown(Real_t Value)
  529.     {
  530.     return floorl(Value);
  531.     }
  532.  
  533. /*----------------------------------------------------------------------------
  534. Func:    RoundIn  --  Round numbers in towards zero.
  535.  
  536. Descr:    
  537. ----------------------------------------------------------------------------*/
  538. Real_t RoundIn(Real_t Value)
  539.     {
  540.     if (Value > 0.0)
  541.         return floorl(Value);
  542.     else
  543.         return ceill(Value);
  544.     }
  545.  
  546. /*----------------------------------------------------------------------------
  547. Func:    RoundOut  --  Round numbers out away from zero.
  548.  
  549. Descr:    
  550. ----------------------------------------------------------------------------*/
  551. Real_t RoundOut(Real_t Value)
  552.     {
  553.     if (Value > 0.0)
  554.         return ceill(Value);
  555.     else
  556.         return floorl(Value);
  557.     }
  558.